home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / FLTK-1.0.6 / test / fractals.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1999-03-25  |  21.5 KB  |  810 lines

  1. //
  2. // "$Id: fractals.cxx,v 1.5.2.1 1999/03/25 13:37:00 mike Exp $"
  3. //
  4. // Fractal drawing demo for the Fast Light Tool Kit (FLTK).
  5. //
  6. // This is a GLUT demo program, with modifications to
  7. // demonstrate how to add fltk controls to a glut program.   The glut
  8. // code is unchanged except for the end (search for fltk to find changes).
  9. //
  10. // Copyright 1998-1999 by Bill Spitzak and others.
  11. //
  12. // This library is free software; you can redistribute it and/or
  13. // modify it under the terms of the GNU Library General Public
  14. // License as published by the Free Software Foundation; either
  15. // version 2 of the License, or (at your option) any later version.
  16. //
  17. // This library is distributed in the hope that it will be useful,
  18. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20. // Library General Public License for more details.
  21. //
  22. // You should have received a copy of the GNU Library General Public
  23. // License along with this library; if not, write to the Free Software
  24. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  25. // USA.
  26. //
  27. // Please report all bugs and problems to "fltk-bugs@easysw.com".
  28. //
  29.  
  30. #include <config.h>
  31. #if !HAVE_GL
  32. #include <FL/Fl.H>
  33. #include <FL/fl_message.H>
  34. int main(int, char**) {
  35.   fl_alert("This demo does not work without GL");
  36.   return 1;
  37. }
  38. #else
  39. /*
  40.  * To compile: cc -o fractals fractals.c -lGL -lGLU -lX11 -lglut -lXmu -lm
  41.  *
  42.  * Usage: fractals
  43.  *
  44.  * Homework 6, Part 2: fractal mountains and fractal trees 
  45.  * (Pretty Late)
  46.  *
  47.  * Draws fractal mountains and trees -- and an island of mountains in water 
  48.  * (I tried having trees on the island but it didn't work too well.)
  49.  *
  50.  * Two viewer modes: polar and flying (both restrained to y>0 for up vector).
  51.  * Keyboard 0->9 and +/- control speed when flying.
  52.  *
  53.  * Only keyboard commands are 0-9 and +/- for speed in flying mode.
  54.  *
  55.  * Fog would make the island look much better, but I couldn't get it to work
  56.  * correctly.  Would line up on -z axis not from eye.
  57.  *
  58.  * Philip Winston - 3/4/95
  59.  * pwinston@hmc.edu
  60.  * http://www.cs.hmc.edu/people/pwinston
  61.  *
  62.  */
  63.  
  64. #include <FL/glut.H>
  65.  
  66. #include <stdio.h>
  67. #include <stdlib.h>
  68. #include <math.h>
  69. #include <limits.h>           /* ULONG_MAX is defined here */
  70. #include <float.h>            /* FLT_MAX is atleast defined here */
  71.  
  72. #include <time.h>  /* for random seed */
  73.  
  74. #include "fracviewer.c" // changed from .h for fltk
  75.  
  76. #if defined(WIN32) || defined(__EMX__)
  77. #define drand48() (((float) rand())/((float) RAND_MAX))
  78. #define srand48(x) (srand((x)))
  79. #endif
  80.  
  81. typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF, 
  82.                MOUNTAIN_MAT, WATER_MAT, LEAF_MAT, TREE_MAT, STEMANDLEAVES,
  83.                AXES } DisplayLists;
  84.  
  85. #define MAXLEVEL 8
  86.  
  87. int Rebuild = 1,        /* Rebuild display list in next display? */
  88.     Fract   = TREE,     /* What fractal are we building */
  89.     Level   = 4;        /* levels of recursion for fractals */     
  90.  
  91. int DrawAxes = 0;       
  92.  
  93. /***************************************************************/
  94. /************************* VECTOR JUNK *************************/
  95. /***************************************************************/
  96.  
  97.   /* print vertex to stderr */
  98. void printvert(float v[3])
  99. {
  100.   fprintf(stderr, "(%f, %f, %f)\n", v[0], v[1], v[2]);
  101. }
  102.  
  103. #if 0    // removed for FL, it is in fracviewer.c
  104.   /* normalizes v */
  105. void normalize(GLfloat v[3])
  106. {
  107.   GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  108.  
  109.   if (d == 0)
  110.     fprintf(stderr, "Zero length vector in normalize\n");
  111.   else
  112.     v[0] /= d; v[1] /= d; v[2] /= d;
  113. }
  114.  
  115.   /* calculates a normalized crossproduct to v1, v2 */
  116. void ncrossprod(float v1[3], float v2[3], float cp[3])
  117. {
  118.   cp[0] = v1[1]*v2[2] - v1[2]*v2[1];
  119.   cp[1] = v1[2]*v2[0] - v1[0]*v2[2];
  120.   cp[2] = v1[0]*v2[1] - v1[1]*v2[0];
  121.   normalize(cp);
  122. }
  123. #endif
  124.  
  125.   /* calculates normal to the triangle designated by v1, v2, v3 */
  126. void triagnormal(float v1[3], float v2[3], float v3[3], float norm[3])
  127. {
  128.   float vec1[3], vec2[3];
  129.  
  130.   vec1[0] = v3[0] - v1[0];  vec2[0] = v2[0] - v1[0];
  131.   vec1[1] = v3[1] - v1[1];  vec2[1] = v2[1] - v1[1];
  132.   vec1[2] = v3[2] - v1[2];  vec2[2] = v2[2] - v1[2];
  133.  
  134.   ncrossprod(vec2, vec1, norm);
  135. }
  136.  
  137. float xzlength(float v1[3], float v2[3])
  138. {
  139.   return sqrt((v1[0] - v2[0])*(v1[0] - v2[0]) +
  140.               (v1[2] - v2[2])*(v1[2] - v2[2]));
  141. }
  142.  
  143. float xzslope(float v1[3], float v2[3])
  144. {
  145.   return ((v1[0] != v2[0]) ? ((v1[2] - v2[2]) / (v1[0] - v2[0]))
  146.                        : FLT_MAX);
  147. }
  148.  
  149.  
  150. /***************************************************************/
  151. /************************ MOUNTAIN STUFF ***********************/
  152. /***************************************************************/
  153.  
  154. GLfloat DispFactor[MAXLEVEL];  /* Array of what to multiply random number
  155.                   by for a given level to get midpoint
  156.                   displacement  */
  157. GLfloat DispBias[MAXLEVEL];  /* Array of what to add to random number
  158.                 before multiplying it by DispFactor */
  159.  
  160. #define NUMRANDS 191
  161. float RandTable[NUMRANDS];  /* hash table of random numbers so we can
  162.                    raise the same midpoints by the same amount */ 
  163.  
  164.          /* The following are for permitting an edge of a moutain to be   */
  165.          /* pegged so it won't be displaced up or down.  This makes it    */
  166.          /* easier to setup scenes and makes a single moutain look better */
  167.  
  168. GLfloat Verts[3][3],    /* Vertices of outside edges of mountain */
  169.         Slopes[3];      /* Slopes between these outside edges */
  170. int     Pegged[3];      /* Is this edge pegged or not */           
  171.  
  172.  /*
  173.   * Comes up with a new table of random numbers [0,1)
  174.   */
  175. void InitRandTable(unsigned int seed)
  176. {
  177.   int i;
  178.  
  179.   srand48((long) seed);
  180.   for (i = 0; i < NUMRANDS; i++)
  181.     RandTable[i] = drand48() - 0.5;
  182. }
  183.  
  184.   /* calculate midpoint and displace it if required */
  185. void Midpoint(GLfloat mid[3], GLfloat v1[3], GLfloat v2[3],
  186.           int edge, int level)
  187. {
  188.   unsigned hash;
  189.  
  190.   mid[0] = (v1[0] + v2[0]) / 2;
  191.   mid[1] = (v1[1] + v2[1]) / 2;
  192.   mid[2] = (v1[2] + v2[2]) / 2;
  193.   if (!Pegged[edge] || (fabs(xzslope(Verts[edge], mid) 
  194.                         - Slopes[edge]) > 0.00001)) {
  195.     srand48((int)((v1[0]+v2[0])*23344));
  196.     hash = unsigned(drand48() * 7334334);
  197.     srand48((int)((v2[2]+v1[2])*43433));
  198.     hash = (unsigned)(drand48() * 634344 + hash) % NUMRANDS;
  199.     mid[1] += ((RandTable[hash] + DispBias[level]) * DispFactor[level]);
  200.   }
  201. }
  202.  
  203.   /*
  204.    * Recursive moutain drawing routine -- from lecture with addition of 
  205.    * allowing an edge to be pegged.  This function requires the above
  206.    * globals to be set, as well as the Level global for fractal level 
  207.    */
  208. static float cutoff = -1;
  209.  
  210. void FMR(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int level)
  211. {
  212.   if (level == Level) {
  213.     GLfloat norm[3];
  214.     if (v1[1] <= cutoff && v2[1]<=cutoff && v3[1]<=cutoff) return;
  215.     triagnormal(v1, v2, v3, norm);
  216.     glNormal3fv(norm);
  217.     glVertex3fv(v1);
  218.     glVertex3fv(v2);
  219.     glVertex3fv(v3);
  220.  
  221.   } else {
  222.     GLfloat m1[3], m2[3], m3[3];
  223.  
  224.     Midpoint(m1, v1, v2, 0, level);
  225.     Midpoint(m2, v2, v3, 1, level);
  226.     Midpoint(m3, v3, v1, 2, level);
  227.  
  228.     FMR(v1, m1, m3, level + 1);
  229.     FMR(m1, v2, m2, level + 1);
  230.     FMR(m3, m2, v3, level + 1);
  231.     FMR(m1, m2, m3, level + 1);
  232.   }
  233. }
  234.  
  235.  /*
  236.   * sets up lookup tables and calls recursive mountain function
  237.   */
  238. void FractalMountain(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3],
  239.                      int pegged[3])
  240. {
  241.   GLfloat lengths[MAXLEVEL];
  242.   GLfloat fraction[8] = { 0.3, 0.3, 0.4, 0.2, 0.3, 0.2, 0.4, 0.4  };
  243.   GLfloat bias[8]     = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1  };
  244.   int i;
  245.   float avglen = (xzlength(v1, v2) + 
  246.                   xzlength(v2, v3) +
  247.           xzlength(v3, v1) / 3);
  248.  
  249.   for (i = 0; i < 3; i++) {
  250.     Verts[0][i] = v1[i];      /* set mountain vertex globals */
  251.     Verts[1][i] = v2[i];
  252.     Verts[2][i] = v3[i];
  253.     Pegged[i] = pegged[i];
  254.   }
  255.  
  256.   Slopes[0] = xzslope(Verts[0], Verts[1]);   /* set edge slope globals */
  257.   Slopes[1] = xzslope(Verts[1], Verts[2]);
  258.   Slopes[2] = xzslope(Verts[2], Verts[0]);
  259.  
  260.   lengths[0] = avglen;          
  261.   for (i = 1; i < Level; i++) {   
  262.     lengths[i] = lengths[i-1]/2;     /* compute edge length for each level */
  263.   }
  264.  
  265.   for (i = 0; i < Level; i++) {     /* DispFactor and DispBias arrays */      
  266.     DispFactor[i] = (lengths[i] * ((i <= 7) ? fraction[i] : fraction[7]));
  267.     DispBias[i]   = ((i <= 7) ? bias[i] : bias[7]);
  268.   } 
  269.  
  270.   glBegin(GL_TRIANGLES);
  271.     FMR(v1, v2, v3, 0);    /* issues no GL but vertex calls */
  272.   glEnd();
  273. }
  274.  
  275.  /*
  276.   * draw a mountain and build the display list
  277.   */
  278. void CreateMountain(void)
  279. {
  280.   GLfloat v1[3] = { 0, 0, -1 }, v2[3] = { -1, 0, 1 }, v3[3] = { 1, 0, 1 };
  281.   int pegged[3] = { 1, 1, 1 };
  282.  
  283.   glNewList(MOUNTAIN, GL_COMPILE);
  284.   glPushAttrib(GL_LIGHTING_BIT);
  285.     glCallList(MOUNTAIN_MAT);
  286.     FractalMountain(v1, v2, v3, pegged);
  287.   glPopAttrib();
  288.   glEndList();
  289. }
  290.  
  291.   /*
  292.    * new random numbers to make a different moutain
  293.    */
  294. void NewMountain(void)
  295. {
  296.   InitRandTable(time(NULL));
  297. }
  298.  
  299. /***************************************************************/
  300. /***************************** TREE ****************************/
  301. /***************************************************************/
  302.  
  303. long TreeSeed;   /* for srand48 - remember so we can build "same tree"
  304.                      at a different level */
  305.  
  306.  /*
  307.   * recursive tree drawing thing, fleshed out from class notes pseudocode 
  308.   */
  309. void FractalTree(int level)
  310. {
  311.   long savedseed;  /* need to save seeds while building tree too */
  312.  
  313.   if (level == Level) {
  314.       glPushMatrix();
  315.         glRotatef(drand48()*180, 0, 1, 0);
  316.         glCallList(STEMANDLEAVES);
  317.       glPopMatrix();
  318.   } else {
  319.     glCallList(STEM);
  320.     glPushMatrix();
  321.     glRotatef(drand48()*180, 0, 1, 0);
  322.     glTranslatef(0, 1, 0);
  323.     glScalef(0.7, 0.7, 0.7);
  324.  
  325.       savedseed = (long)((ulong)drand48()*ULONG_MAX);
  326.       glPushMatrix();    
  327.         glRotatef(110 + drand48()*40, 0, 1, 0);
  328.         glRotatef(30 + drand48()*20, 0, 0, 1);
  329.         FractalTree(level + 1);
  330.       glPopMatrix();
  331.  
  332.       srand48(savedseed);
  333.       savedseed = (long)((ulong)drand48()*ULONG_MAX);
  334.       glPushMatrix();
  335.         glRotatef(-130 + drand48()*40, 0, 1, 0);
  336.         glRotatef(30 + drand48()*20, 0, 0, 1);
  337.         FractalTree(level + 1);
  338.       glPopMatrix();
  339.  
  340.       srand48(savedseed);
  341.       glPushMatrix();
  342.         glRotatef(-20 + drand48()*40, 0, 1, 0);
  343.         glRotatef(30 + drand48()*20, 0, 0, 1);
  344.         FractalTree(level + 1);
  345.       glPopMatrix();
  346.  
  347.     glPopMatrix();
  348.   }
  349. }
  350.  
  351.   /*
  352.    * Create display lists for a leaf, a set of leaves, and a stem
  353.    */
  354. void CreateTreeLists(void)
  355. {
  356.   GLUquadricObj *cylquad = gluNewQuadric();
  357.   int i;
  358.  
  359.   glNewList(STEM, GL_COMPILE);
  360.   glPushMatrix();
  361.     glRotatef(-90, 1, 0, 0);
  362.     gluCylinder(cylquad, 0.1, 0.08, 1, 10, 2 );
  363.   glPopMatrix();
  364.   glEndList();
  365.  
  366.   glNewList(LEAF, GL_COMPILE);  /* I think this was jeff allen's leaf idea */
  367.     glBegin(GL_TRIANGLES);
  368.       glNormal3f(-0.1, 0, 0.25);  /* not normalized */
  369.       glVertex3f(0, 0, 0);
  370.       glVertex3f(0.25, 0.25, 0.1);
  371.       glVertex3f(0, 0.5, 0);
  372.  
  373.       glNormal3f(0.1, 0, 0.25);
  374.       glVertex3f(0, 0, 0);
  375.       glVertex3f(0, 0.5, 0);
  376.       glVertex3f(-0.25, 0.25, 0.1);
  377.     glEnd();
  378.   glEndList();
  379.  
  380.   glNewList(STEMANDLEAVES, GL_COMPILE);
  381.   glPushMatrix();
  382.   glPushAttrib(GL_LIGHTING_BIT);
  383.     glCallList(STEM);
  384.     glCallList(LEAF_MAT);
  385.     for(i = 0; i < 3; i++) {
  386.       glTranslatef(0, 0.333, 0);
  387.       glRotatef(90, 0, 1, 0);
  388.       glPushMatrix();
  389.         glRotatef(0, 0, 1, 0);
  390.         glRotatef(50, 1, 0, 0);
  391.         glCallList(LEAF);
  392.       glPopMatrix();
  393.       glPushMatrix();
  394.         glRotatef(180, 0, 1, 0);
  395.         glRotatef(60, 1, 0, 0);
  396.         glCallList(LEAF);
  397.       glPopMatrix();
  398.     }
  399.   glPopAttrib();
  400.   glPopMatrix();
  401.   glEndList();
  402.  
  403.   gluDeleteQuadric(cylquad);
  404. }
  405.  
  406.  /*
  407.   * draw and build display list for tree
  408.   */
  409. void CreateTree(void)
  410. {
  411.   srand48(TreeSeed);
  412.  
  413.   glNewList(TREE, GL_COMPILE);
  414.     glPushMatrix();
  415.     glPushAttrib(GL_LIGHTING_BIT);
  416.     glCallList(TREE_MAT);
  417.     glTranslatef(0, -1, 0);
  418.     FractalTree(0);
  419.     glPopAttrib();
  420.     glPopMatrix();
  421.   glEndList();  
  422. }
  423.  
  424.  /*
  425.   * new seed for a new tree (groan)
  426.   */
  427. void NewTree(void)
  428. {
  429.   TreeSeed = time(NULL);
  430. }
  431.  
  432. /***************************************************************/
  433. /*********************** FRACTAL PLANET ************************/
  434. /***************************************************************/
  435.  
  436. void CreateIsland(void)
  437. {
  438.   cutoff = .06;
  439.   CreateMountain();
  440.   cutoff = -1;
  441.   glNewList(ISLAND, GL_COMPILE);
  442.   glPushAttrib(GL_LIGHTING_BIT);
  443.   glMatrixMode(GL_MODELVIEW);
  444.   glPushMatrix();
  445.     glCallList(WATER_MAT);
  446.  
  447.     glBegin(GL_QUADS);
  448.       glNormal3f(0, 1, 0);
  449.       glVertex3f(10, 0.01, 10);
  450.       glVertex3f(10, 0.01, -10);
  451.       glVertex3f(-10, 0.01, -10);
  452.       glVertex3f(-10, 0.01, 10);
  453.     glEnd();
  454.  
  455.     glPushMatrix();
  456.     glTranslatef(0, -0.1, 0);
  457.     glCallList(MOUNTAIN);
  458.     glPopMatrix();
  459.  
  460.     glPushMatrix();
  461.     glRotatef(135, 0, 1, 0);
  462.     glTranslatef(0.2, -0.15, -0.4);
  463.     glCallList(MOUNTAIN);
  464.     glPopMatrix();
  465.  
  466.     glPushMatrix();
  467.     glRotatef(-60, 0, 1, 0);
  468.     glTranslatef(0.7, -0.07, 0.5);
  469.     glCallList(MOUNTAIN);
  470.     glPopMatrix();
  471.  
  472.     glPushMatrix();
  473.     glRotatef(-175, 0, 1, 0);
  474.     glTranslatef(-0.7, -0.05, -0.5);
  475.     glCallList(MOUNTAIN);
  476.     glPopMatrix();
  477.  
  478.     glPushMatrix();
  479.     glRotatef(165, 0, 1, 0);
  480.     glTranslatef(-0.9, -0.12, 0.0);
  481.     glCallList(MOUNTAIN);
  482.     glPopMatrix();
  483.  
  484.   glPopMatrix();
  485.   glPopAttrib();
  486.   glEndList();  
  487. }
  488.  
  489.  
  490. void NewFractals(void)
  491. {
  492.   NewMountain();
  493.   NewTree();
  494. }
  495.  
  496. void Create(int fract)
  497. {
  498.   switch(fract) {
  499.     case MOUNTAIN:
  500.       CreateMountain();
  501.       break;
  502.     case TREE:
  503.       CreateTree();
  504.       break;
  505.     case ISLAND:
  506.       CreateIsland();
  507.       break;
  508.   }
  509. }
  510.  
  511.  
  512.  
  513. /***************************************************************/
  514. /**************************** OPENGL ***************************/
  515. /***************************************************************/
  516.  
  517.  
  518. void SetupMaterials(void)
  519. {
  520.   GLfloat mtn_ambuse[] =   { 0.426, 0.256, 0.108, 1.0 };
  521.   GLfloat mtn_specular[] = { 0.394, 0.272, 0.167, 1.0 };
  522.   GLfloat mtn_shininess[] = { 10 };
  523.  
  524.   GLfloat water_ambuse[] =   { 0.0, 0.1, 0.5, 1.0 };
  525.   GLfloat water_specular[] = { 0.0, 0.1, 0.5, 1.0 };
  526.   GLfloat water_shininess[] = { 10 };
  527.  
  528.   GLfloat tree_ambuse[] =   { 0.4, 0.25, 0.1, 1.0 };
  529.   GLfloat tree_specular[] = { 0.0, 0.0, 0.0, 1.0 };
  530.   GLfloat tree_shininess[] = { 0 };
  531.  
  532.   GLfloat leaf_ambuse[] =   { 0.0, 0.8, 0.0, 1.0 };
  533.   GLfloat leaf_specular[] = { 0.0, 0.8, 0.0, 1.0 };
  534.   GLfloat leaf_shininess[] = { 10 };
  535.  
  536.   glNewList(MOUNTAIN_MAT, GL_COMPILE);
  537.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mtn_ambuse);
  538.     glMaterialfv(GL_FRONT, GL_SPECULAR, mtn_specular);
  539.     glMaterialfv(GL_FRONT, GL_SHININESS, mtn_shininess);
  540.   glEndList();
  541.  
  542.   glNewList(WATER_MAT, GL_COMPILE);
  543.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, water_ambuse);
  544.     glMaterialfv(GL_FRONT, GL_SPECULAR, water_specular);
  545.     glMaterialfv(GL_FRONT, GL_SHININESS, water_shininess);
  546.   glEndList();
  547.  
  548.   glNewList(TREE_MAT, GL_COMPILE);
  549.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tree_ambuse);
  550.     glMaterialfv(GL_FRONT, GL_SPECULAR, tree_specular);
  551.     glMaterialfv(GL_FRONT, GL_SHININESS, tree_shininess);
  552.   glEndList();
  553.  
  554.   glNewList(LEAF_MAT, GL_COMPILE);
  555.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, leaf_ambuse);
  556.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, leaf_specular);
  557.     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, leaf_shininess);
  558.   glEndList();
  559. }
  560.  
  561. void myGLInit(void)
  562. {
  563.   GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
  564.   GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  565.   GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  566.   GLfloat light_position[] = { 0.0, 0.3, 0.3, 0.0 };
  567.  
  568.   GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
  569.  
  570.   glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  571.   glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  572.   glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
  573.   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  574.     
  575.   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
  576.  
  577.   glEnable(GL_LIGHTING);
  578.   glEnable(GL_LIGHT0);
  579.  
  580.   glDepthFunc(GL_LEQUAL);
  581.   glEnable(GL_DEPTH_TEST);
  582.  
  583.   glEnable(GL_NORMALIZE);
  584. #if 0
  585.   glEnable(GL_CULL_FACE);
  586.   glCullFace(GL_BACK);
  587. #endif
  588.  
  589.   glShadeModel(GL_SMOOTH);
  590. #if 0
  591.   glEnable(GL_BLEND);
  592.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  593. #endif
  594.  
  595.   SetupMaterials();
  596.   CreateTreeLists();
  597.  
  598.   glFlush();
  599.  
  600. /***************************************************************/
  601. /************************ GLUT STUFF ***************************/
  602. /***************************************************************/
  603.  
  604. void reshape(int w, int h)
  605. {
  606.   glViewport(0,0,w,h);
  607.   glMatrixMode(GL_PROJECTION);
  608.   glLoadIdentity();
  609.   gluPerspective(60.0, (GLdouble)w/h, 0.01, 100);
  610.   glPushMatrix();
  611.   glMatrixMode(GL_MODELVIEW);
  612.   glFlush();
  613. }
  614.  
  615. void display(void)
  616.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  617.   glFlush();
  618.  
  619.   glMatrixMode(GL_PROJECTION);
  620.   glPopMatrix();
  621.   glPushMatrix();  /* clear of last viewing xform, leaving perspective */
  622.  
  623.   agvViewTransform();
  624.  
  625.   glMatrixMode(GL_MODELVIEW);
  626.   glLoadIdentity();
  627.  
  628.   if (Rebuild) {
  629.     Create(Fract);
  630.     Rebuild = 0;
  631.   }
  632.  
  633.   glCallList(Fract);
  634.  
  635.   if (DrawAxes)
  636.     glCallList(AXES);
  637.  
  638.   glutSwapBuffers();
  639.   glFlush();
  640. }
  641.  
  642. void visible(int v)
  643. {
  644.   if (v == GLUT_VISIBLE)
  645.     agvSetAllowIdle(1);
  646.   else {
  647.     glutIdleFunc(NULL);
  648.     agvSetAllowIdle(0);
  649.   }
  650. }
  651.  
  652. void menuuse(int v)
  653. {
  654.   if (v == GLUT_MENU_NOT_IN_USE)
  655.     agvSetAllowIdle(1);
  656.   else {
  657.     glutIdleFunc(NULL);
  658.     agvSetAllowIdle(0);
  659.   }
  660. }
  661.  
  662. /***************************************************************/
  663. /******************* MENU SETUP & HANDLING *********************/
  664. /***************************************************************/
  665.  
  666. typedef enum { MENU_QUIT, MENU_RAND, MENU_MOVE, MENU_AXES } MenuChoices;
  667.  
  668. void setlevel(int value)
  669. {
  670.   Level = value;
  671.   Rebuild = 1;
  672.   glutPostRedisplay();
  673. }
  674.  
  675. void choosefract(int value)
  676. {
  677.   Fract = value;
  678.   Rebuild = 1;
  679.   glutPostRedisplay();
  680. }
  681.  
  682. void handlemenu(int value)
  683. {
  684.   switch (value) {
  685.     case MENU_QUIT:
  686.       exit(0);
  687.       break;
  688.     case MENU_RAND:
  689.       NewFractals();
  690.       Rebuild = 1;
  691.       glutPostRedisplay();
  692.       break;
  693.     case MENU_AXES:
  694.       DrawAxes = !DrawAxes;
  695.       glutPostRedisplay();
  696.       break;
  697.     }
  698. }
  699.  
  700. void MenuInit(void)
  701. {
  702.   int submenu3, submenu2, submenu1;
  703.  
  704.   submenu1 = glutCreateMenu(setlevel);
  705.   glutAddMenuEntry("0", 0);  glutAddMenuEntry("1", 1);
  706.   glutAddMenuEntry("2", 2);  glutAddMenuEntry("3", 3);
  707.   glutAddMenuEntry("4", 4);  glutAddMenuEntry("5", 5);
  708.   glutAddMenuEntry("6", 6);  glutAddMenuEntry("7", 7);
  709.   glutAddMenuEntry("8", 8);
  710.  
  711.   submenu2 = glutCreateMenu(choosefract);
  712.   glutAddMenuEntry("Moutain", MOUNTAIN);
  713.   glutAddMenuEntry("Tree", TREE);
  714.   glutAddMenuEntry("Island", ISLAND);
  715.  
  716.   submenu3 = glutCreateMenu(agvSwitchMoveMode);
  717.   glutAddMenuEntry("Flying", FLYING);
  718.   glutAddMenuEntry("Polar", POLAR);
  719.  
  720.   glutCreateMenu(handlemenu);
  721.   glutAddSubMenu("Level", submenu1);
  722.   glutAddSubMenu("Fractal", submenu2);
  723.   glutAddSubMenu("Movement", submenu3);
  724.   glutAddMenuEntry("New Fractal",      MENU_RAND);
  725.   glutAddMenuEntry("Toggle Axes", MENU_AXES);
  726.   glutAddMenuEntry("Quit",             MENU_QUIT);
  727.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  728. }
  729.  
  730.  
  731. /***************************************************************/
  732. /**************************** MAIN *****************************/
  733. /***************************************************************/
  734.  
  735. // fltk-style callbacks to Glut menu callback translators:
  736. void setlevel(Fl_Widget*, void *value) {setlevel(long(value));}
  737.  
  738. void choosefract(Fl_Widget*, void *value) {choosefract(long(value));}
  739.  
  740. void handlemenu(Fl_Widget*, void *value) {handlemenu(long(value));}
  741.  
  742. #include <FL/Fl_Button.H>
  743. #include <FL/Fl_Group.H>
  744. #include <FL/Fl_Window.H>
  745.  
  746. int main(int argc, char** argv)
  747. {
  748. //  glutInit(&argc, argv); // this line removed for fltk
  749.  
  750.   // create fltk window:
  751.   Fl_Window window(512+20, 512+100);
  752.   window.resizable(window);
  753.  
  754.   // create a bunch of buttons:
  755.   Fl_Group *g = new Fl_Group(110,50,400-110,30,"Level:");
  756.   g->align(FL_ALIGN_LEFT);
  757.   g->begin();
  758.   Fl_Button *b;
  759.   b = new Fl_Button(110,50,30,30,"0"); b->callback(setlevel,(void*)0);
  760.   b = new Fl_Button(140,50,30,30,"1"); b->callback(setlevel,(void*)1);
  761.   b = new Fl_Button(170,50,30,30,"2"); b->callback(setlevel,(void*)2);
  762.   b = new Fl_Button(200,50,30,30,"3"); b->callback(setlevel,(void*)3);
  763.   b = new Fl_Button(230,50,30,30,"4"); b->callback(setlevel,(void*)4);
  764.   b = new Fl_Button(260,50,30,30,"5"); b->callback(setlevel,(void*)5);
  765.   b = new Fl_Button(290,50,30,30,"6"); b->callback(setlevel,(void*)6);
  766.   b = new Fl_Button(320,50,30,30,"7"); b->callback(setlevel,(void*)7);
  767.   b = new Fl_Button(350,50,30,30,"8"); b->callback(setlevel,(void*)8);
  768.   g->end();
  769.  
  770.   b = new Fl_Button(400,50,100,30,"New Fractal"); b->callback(handlemenu,(void*)MENU_RAND);
  771.   
  772.   b = new Fl_Button( 10,10,100,30,"Mountain"); b->callback(choosefract,(void*)MOUNTAIN);
  773.   b = new Fl_Button(110,10,100,30,"Tree"); b->callback(choosefract,(void*)TREE);
  774.   b = new Fl_Button(210,10,100,30,"Island"); b->callback(choosefract,(void*)ISLAND);
  775.   b = new Fl_Button(400,10,100,30,"Quit"); b->callback(handlemenu,(void*)MENU_QUIT);
  776.  
  777.  
  778.   window.show(argc,argv); // glut will die unless parent window visible
  779.   window.begin(); // this will cause Glut window to be a child
  780.   glutInitWindowSize(512, 512);
  781.   glutInitWindowPosition(10,90); // place it inside parent window
  782.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
  783.   glutCreateWindow("Fractal Planet?");
  784.   window.end();
  785.   window.resizable(glut_window);
  786.  
  787.   agvInit(1); /* 1 cause we don't have our own idle */
  788.  
  789.   glutReshapeFunc(reshape);
  790.   glutDisplayFunc(display);
  791.   glutVisibilityFunc(visible);
  792.   glutMenuStateFunc(menuuse);
  793.  
  794.   NewFractals();
  795.   agvMakeAxesList(AXES);
  796.   myGLInit(); 
  797.   MenuInit();
  798.  
  799.   glutMainLoop(); // you could use Fl::run() instead
  800.  
  801.   return 0;
  802. }
  803. #endif
  804.  
  805. //
  806. // End of "$Id: fractals.cxx,v 1.5.2.1 1999/03/25 13:37:00 mike Exp $".
  807. //
  808.